﻿using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Drawing;
using SLogo.Helper;

namespace SLogo.Drawing
{
    /// <summary>
    /// 绘图类，实现与矢量图形有关的动作
    /// </summary>
    public class VectorGraphics : SlogoDrawing
    {
        private XmlDocument xmldoc; //创建的svg文件
        private Color _penColor;//画笔颜色
        private double _width;//宽度
        private double _height;//高度

        /// <summary>
        /// 创建画板，颜色默认为白色
        /// </summary>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        public VectorGraphics(double width, double height)
        {
            _penColor = Color.Black;//默认为黑色
            _width = width;
            _height = height;
            xmldoc = new XmlDocument();
            //加入XML的声明段落,<?xml version="1.0" standalone="no"?>
            XmlDeclaration xmldecl;
            xmldecl = xmldoc.CreateXmlDeclaration("1.0","", "no");
            xmldoc.AppendChild(xmldecl);
            XmlElement svg = xmldoc.CreateElement("", "svg", "");
            svg.SetAttribute("width", width.ToString()); //设置svg图片的高和宽
            svg.SetAttribute("height", height.ToString());
            svg.SetAttribute("xmlns", "http://www.w3.org/2000/svg");
            svg.SetAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
            svg.SetAttribute("encoding","UTF-8");
            xmldoc.AppendChild(svg);
        }

        /// <summary>
        /// 设置画笔颜色
        /// </summary>
        /// <param name="color">画笔颜色</param>
        public override void SetPenColor(Color color)
        {
            _penColor = color;
        }

        /// <summary>
        /// 画直线
        /// </summary>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="x2"></param>
        /// <param name="y2"></param>
        public override void Line(double x1, double y1, double x2, double y2)
        {
            x1 = _width / 2 + x1;
            x2 = _width / 2 + x2;
            y1 = _height / 2 - y1;
            y2 = _height / 2 - y2;
            XmlNode svg = xmldoc.GetElementsByTagName("svg")[0];
            XmlElement line = xmldoc.CreateElement("line");
            line.SetAttribute("x1", x1.ToString());
            line.SetAttribute("y1", y1.ToString());
            line.SetAttribute("x2", x2.ToString());
            line.SetAttribute("y2", y2.ToString());
            line.SetAttribute("style", String.Format("stroke:rgb({0},{1},{2});stroke-width:1;stroke-opacity:{3}",
                _penColor.R, _penColor.G, _penColor.B, _penColor.A/255.0)); //采用画笔的颜色
            svg.AppendChild(line);
        }

        /// <summary>
        /// 画矩形外框
        /// </summary>
        /// <param name="x">中心x坐标</param>
        /// <param name="y">中心y坐标</param>
        /// <param name="width">矩形宽度</param>
        /// <param name="height">矩形高度</param>
        /// <param name="angle">角度</param>
        public override void Rectangle(double x, double y, double width, double height,double angle)
        {
            double realx = _width / 2 + x;
            double realy = _height / 2 - y;
            x = _width/2 + x - width/2;
            y = _width/2 - y - height/2;
            angle = angle * 180 / Math.PI;
            XmlNode svg = xmldoc.GetElementsByTagName("svg")[0];
            XmlElement rect = xmldoc.CreateElement("rect");
            rect.SetAttribute("x", x.ToString());
            rect.SetAttribute("y", y.ToString());
            rect.SetAttribute("width", width.ToString());
            rect.SetAttribute("height", height.ToString());
            rect.SetAttribute("transform", String.Format("rotate({0} {1},{2})", angle, realx, realy));
            rect.SetAttribute("style", String.Format("fill-opacity:0;stroke:rgb({0},{1},{2});stroke-width:1;stroke-opacity:{3}",
                _penColor.R, _penColor.G, _penColor.B, _penColor.A / 255.0));
            svg.AppendChild(rect);
        }

        /// <summary>
        /// 填充矩形区域，颜色为color
        /// </summary>
        /// <param name="x">中心x坐标</param>
        /// <param name="y">中心y坐标</param>
        /// <param name="width">矩形宽度</param>
        /// <param name="height">矩形高度</param>
        /// <param name="angle">角度</param>
        /// <param name="color">颜色</param>
        public override void Rectangle(double x, double y, double width, double height, double angle, Color color)
        {
            double realx = _width/2 + x;
            double realy = _height/2 - y;
            x = _width/2 + x - width/2;
            y = _width/2 - y - height/2;
            angle = angle * 180 / Math.PI;
            XmlNode svg = xmldoc.GetElementsByTagName("svg")[0];
            XmlElement rect = xmldoc.CreateElement("rect");
            rect.SetAttribute("x", x.ToString());
            rect.SetAttribute("y", y.ToString());
            rect.SetAttribute("width", width.ToString());
            rect.SetAttribute("height", height.ToString());
            rect.SetAttribute("transform", String.Format("rotate({0} {1},{2})", angle, realx, realy));
            rect.SetAttribute("style",
                              String.Format(
                                  "fill:rgb({0},{1},{2});fill-opacity:{3};stroke-width:1;stroke:rgb({4},{5},{6});stroke-opacity:{7}",
                                  color.R, color.G, color.B, color.A/255.0,
                                  _penColor.R, _penColor.G, _penColor.B, _penColor.A/255.0));
            svg.AppendChild(rect);
        }

        /// <summary>
        /// 画椭圆框
        /// </summary>
        /// <param name="x">中心x坐标</param>
        /// <param name="y">中心y坐标</param>
        /// <param name="width">矩形宽度</param>
        /// <param name="height">矩形高度</param>
        /// <param name="angle">角度</param>
        public override void Ellipse(double x, double y, double width, double height,double angle)
        {
            x = _width / 2 + x;
            y = _height / 2 - y;
            width /= 2;
            height /= 2;
            angle = angle * 180 / Math.PI;
            XmlNode svg = xmldoc.GetElementsByTagName("svg")[0];
            XmlElement ellipse = xmldoc.CreateElement("ellipse");
            ellipse.SetAttribute("cx", x.ToString());
            ellipse.SetAttribute("cy", y.ToString());
            ellipse.SetAttribute("rx", width.ToString());
            ellipse.SetAttribute("ry", height.ToString());
            ellipse.SetAttribute("transform", String.Format("rotate({0} {1},{2})", angle, x, y));
            ellipse.SetAttribute("style", String.Format("fill-opacity:0;stroke:rgb({0},{1},{2});stroke-width:1;stroke-opacity:{3}",
                                                        _penColor.R, _penColor.G, _penColor.B, _penColor.A/255.0));
            svg.AppendChild(ellipse);
        }


        /// <summary>
        /// 填充椭圆形区域,颜色为color
        /// </summary>
        /// <param name="x">中心x坐标</param>
        /// <param name="y">中心y坐标</param>
        /// <param name="width">矩形宽度</param>
        /// <param name="height">矩形高度</param>
        /// <param name="angle">角度</param>
        /// <param name="color">颜色</param>
        public override void Ellipse(double x, double y, double width, double height, double angle, Color color)
        {
            x = _width/2 + x;
            y = _width/2 - y;
            width /= 2;
            height /= 2;
            angle = angle*180/Math.PI;
            XmlNode svg = xmldoc.GetElementsByTagName("svg")[0];
            XmlElement ellipse = xmldoc.CreateElement("ellipse");
            ellipse.SetAttribute("cx", x.ToString());
            ellipse.SetAttribute("cy", y.ToString());
            ellipse.SetAttribute("rx", width.ToString());
            ellipse.SetAttribute("ry", height.ToString());
            ellipse.SetAttribute("transform", String.Format("rotate({0} {1},{2})", angle, x, y));
            ellipse.SetAttribute("style",
                                 String.Format(
                                     "fill:rgb({0},{1},{2});fill-opacity:{3};stroke-width:1;stroke:rgb({4},{5},{6});stroke-opacity:{7}",
                                     color.R, color.G, color.B, color.A/255.0,
                                     _penColor.R, _penColor.G, _penColor.B, _penColor.A/255.0));
            svg.AppendChild(ellipse);
        }

        /// <summary>
        /// 画多边形的框
        /// </summary>
        /// <param name="points">多边形依次的坐标点</param>
        public override void Polygon(PointF[] points)
        {
            for (int i = 0; i < points.Length; i++)
            {
                points[i].X = (float)_width / 2 + points[i].X;
                points[i].Y = (float)_height / 2 - points[i].Y;
            }
            XmlNode svg = xmldoc.GetElementsByTagName("svg")[0];
            XmlElement xmlPath = xmldoc.CreateElement("path");
            //各点之间画直线实现
            string path = "M " + points[0].X + " " + points[0].Y + " ";
            for (int i = 1; i < points.Count(); i++)
            {
                path += "L " + points[i].X + " " + points[i].Y + " ";
            }
            path += "L " + points[0].X + " " + points[0].Y;
            xmlPath.SetAttribute("d", path);
            xmlPath.SetAttribute("style",
                                 String.Format(
                                     "stroke:rgb({0},{1},{2});stroke-width:1;stroke-opacity:{3};fill-opacity:0",
                                     _penColor.R, _penColor.G, _penColor.B, _penColor.A/255.0));
            svg.AppendChild(xmlPath);
        }

        /// <summary>
        /// 填充多边形框
        /// </summary>
        /// <param name="points">多边形依次的坐标点</param>
        /// <param name="color">填充色</param>
        public override void Polygon(PointF[] points, Color color)
        {
            for (int i = 0; i < points.Length; i++)
            {
                points[i].X = (float)_width / 2 + points[i].X;
                points[i].Y = (float)_height / 2 - points[i].Y;
            }
            XmlNode svg = xmldoc.GetElementsByTagName("svg")[0];
            XmlElement xmlPath = xmldoc.CreateElement("path");
            string path = "M " + points[0].X + " " + points[0].Y + " ";
            for (int i = 1; i < points.Count(); i++)
            {
                path += "L " + points[i].X + " " + points[i].Y + " ";
            }
            path += "L " + points[0].X + " " + points[0].Y;
            xmlPath.SetAttribute("d", path);
            xmlPath.SetAttribute("style",
                                 String.Format(
                                     "fill:rgb({0},{1},{2});fill-opacity:{3};stroke-width:1;stroke:rgb({4},{5},{6});stroke-opacity:{7}",
                                     color.R, color.G, color.B, color.A/255.0,
                                     _penColor.R, _penColor.G, _penColor.B, _penColor.A/255.0));
            svg.AppendChild(xmlPath);
        }

        /// <summary>
        /// 按一定角度，一定坐标输出打印文本
        /// </summary>
        /// <param name="outStr">打印字符串</param>
        /// <param name="angle">角度</param>
        /// <param name="x">坐标x</param>
        /// <param name="y">坐标y</param>
        public override void Text(string outStr, double angle, double x, double y)
        {
            x = _width / 2 + x;
            y = _height / 2 - y;
            XmlNode svg = xmldoc.GetElementsByTagName("svg")[0];
            XmlElement text = xmldoc.CreateElement("text");
            text.InnerText = outStr;
            text.SetAttribute("x", x.ToString());
            text.SetAttribute("y", y.ToString());
            text.SetAttribute("font-family", "Arial");
            text.SetAttribute("font-size", "16");
            text.SetAttribute("transform", String.Format("rotate({0} {1},{2})",angle*180/Math.PI,x,y));
            text.SetAttribute("style", "fill:black");
            svg.AppendChild(text);
        }

        /// <summary>
        /// 清除画板内容，颜色设为初始背景色
        /// </summary>
        public override void Clear(Color color)
        {
            XmlElement svg = xmldoc.GetElementsByTagName("svg")[0] as XmlElement;
            svg.RemoveAll();
            XmlElement rect = xmldoc.CreateElement("rect");
            rect.SetAttribute("x", "0");
            rect.SetAttribute("y", "0");
            rect.SetAttribute("width", svg.GetAttribute("width"));
            rect.SetAttribute("height", svg.GetAttribute("height"));
            rect.SetAttribute("style", String.Format("fill:{0};stroke-opacity:0", color.ToArgb() & 0x00FFFFFF));
            svg.AppendChild(rect);
        }

        /// <summary>
        /// 输出xml
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="border"></param>
        public override void Print(double width, double height, double top, double buttom, double left, double right)
        {
            //if (top == -1)
            //{
                Guid guid = Guid.NewGuid();
                string path = Environment.GetEnvironmentVariable("TEMP") + "\\" + guid + ".temp";
                xmldoc.Save(path);
                FileStream fs = new FileStream(path, FileMode.Open);
                byte[] by = new byte[fs.Length];
                fs.Read(by, 0, (int)fs.Length);
                fs.Close();
                ConsoleHelper.StdOut(by);
                File.Delete(path);
            //}
            //else
            //{
            //    Color color = SLogo.Command.TurtleCommand.BackgroundColor;
                //XmlNode svg = xmldoc.GetElementsByTagName("svg")[0];
                //svg.Attributes["width"].Value = width.ToString();
                //svg.Attributes["height"].Value = height.ToString();
                //XmlAttribute style = xmldoc.CreateAttribute("style");
                //style.Value = "shape-rendering:geometricPrecision;";
                //svg.Attributes.SetNamedItem(style);
                //XmlAttribute view = xmldoc.CreateAttribute("viewbox");
                //view.Value = String.Format("{0} {1} {2} {3}", -_width / 2 - width / 2 - left, -height / 2 - height / 2 - top,
                //                               width + right + left, height + buttom + top);
                //svg.Attributes.SetNamedItem(view);
                //XmlElement line1 = xmldoc.CreateElement("line");
                //line1.SetAttribute("x1", "0");
                //line1.SetAttribute("y1", "0");
                //line1.SetAttribute("x2", "0");
                //line1.SetAttribute("y2", height.ToString());
                //line1.SetAttribute("style", String.Format("stroke:rgb({0},{1},{2});stroke-width:{3};stroke-opacity:{4}",
                //                                          color.R, color.G, color.B, left, color.A/255.0)); //采用画笔的颜色
                //svg.AppendChild(line1);
                //XmlElement line2 = xmldoc.CreateElement("line");
                //line2.SetAttribute("x1", width.ToString());
                //line2.SetAttribute("y1", "0");
                //line2.SetAttribute("x2", width.ToString());
                //line2.SetAttribute("y2", height.ToString());
                //line2.SetAttribute("style", String.Format("stroke:rgb({0},{1},{2});stroke-width:{3};stroke-opacity:{4}",
                //                                          color.R, color.G, color.B, right, color.A/255.0)); //采用画笔的颜色
                //svg.AppendChild(line2);
                //XmlElement line3 = xmldoc.CreateElement("line");
                //line3.SetAttribute("x1", "0");
                //line3.SetAttribute("y1", "0");
                //line3.SetAttribute("x2", width.ToString());
                //line3.SetAttribute("y2", "0");
                //line3.SetAttribute("style", String.Format("stroke:rgb({0},{1},{2});stroke-width:{3};stroke-opacity:{4}",
                //                                          color.R, color.G, color.B, top, color.A/255.0)); //采用画笔的颜色
                //svg.AppendChild(line3);
                //XmlElement line4 = xmldoc.CreateElement("line");
                //line4.SetAttribute("x1", "0");
                //line4.SetAttribute("y1", height.ToString());
                //line4.SetAttribute("x2", width.ToString());
                //line4.SetAttribute("y2", height.ToString());
                //line4.SetAttribute("style", String.Format("stroke:rgb({0},{1},{2});stroke-width:{3};stroke-opacity:{4}",
                //                                          color.R, color.G, color.B, buttom, color.A/255.0)); //采用画笔的颜色
                //svg.AppendChild(line4);
            //    Guid guid = Guid.NewGuid();
            //    string path = Environment.GetEnvironmentVariable("TEMP") + "\\" + guid + ".temp";
            //    xmldoc.Save(path);
            //    FileStream fs = new FileStream(path, FileMode.Open);
            //    byte[] by = new byte[fs.Length];
            //    fs.Read(by, 0, (int) fs.Length);
            //    fs.Close();
            //    ConsoleHelper.StdOut(by);
            //    File.Delete(path);
            //}
        }
    }
}
